package it.polimi.comorazio.activities;

import it.polimi.comorazio.BlueLine;
import it.polimi.comorazio.R;
import it.polimi.comorazio.data.DataBaseHelper;
import it.polimi.comorazio.data.PointOfInterestVo;
import it.polimi.comorazio.fragments.PointOfInterestDetailFragment;

import java.util.ArrayList;
import java.util.List;

import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.ItemizedIconOverlay.OnItemGestureListener;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.OverlayItem;
import org.osmdroid.views.overlay.PathOverlay;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

public class Tour extends Activity implements
		OnItemGestureListener<OverlayItem>, LocationListener {

	public static final String ARG_POI_ID = "poi_id";

	private DataBaseHelper dbHelper;
	private MapView mapView;
	private TextView poiName;
	private TextView poiId;
	private ItemizedIconOverlay<OverlayItem> itemizedoverlay;
	private ItemizedIconOverlay<OverlayItem> myLocationOverlay;
	private String providerName;
	private LocationManager locationManager;
	private BlueLine blueLine;
	private Location myLocation;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_tour);

		((ImageButton) findViewById(R.id.takeMeThere)).setEnabled(false);
		((ImageButton) findViewById(R.id.takeMeThere)).setClickable(false);

		dbHelper = new DataBaseHelper(this);
		dbHelper.createDataBase();
		dbHelper.openDataBase();

		mapView = (MapView) findViewById(R.id.mapview);
		poiName = (TextView) findViewById(R.id.tour_poi_name);
		poiId = (TextView) findViewById(R.id.poiId);
		mapView.setBuiltInZoomControls(true);
		mapView.setMultiTouchControls(true);

		GeoPoint comoCity = new GeoPoint(45.812253, 9.085865);
		// Center and zoom to Como city
		mapView.getController().setZoom(14);
		mapView.getController().setCenter(comoCity);

		List<Overlay> mapOverlays = mapView.getOverlays();
		Drawable drawable = this.getResources().getDrawable(
				R.drawable.red_circle);

		ArrayList<OverlayItem> itemArray = new ArrayList<OverlayItem>();

		Cursor c = dbHelper.getAllPointsOfInterest();

		c.moveToFirst();
		while (!c.isAfterLast()) {
			PointOfInterestVo poi = new PointOfInterestVo(c, c.getPosition(), DataBaseHelper.getCurrentLocale(this));
			Log.d(this.getClass().getCanonicalName(), poi.toString());
			if (poi.getLatitude() != 0 && poi.getLongitude() != 0) {
				OverlayItem overlayitem = new OverlayItem(poi.getName(),
						poi.getDescription(), new GeoPoint(poi.getLatitude(),
								poi.getLongitude()));
				overlayitem.setMarker(drawable);
				itemArray.add(overlayitem);
			}
			c.moveToNext();
		}
		c.close();

		itemizedoverlay = new ItemizedIconOverlay<OverlayItem>(
				getApplicationContext(), itemArray, this);

		((TextView) findViewById(R.id.totalPois)).setText(String
				.valueOf(itemizedoverlay.size()));

		// Select indicated POI on the Bundle or the first one by default
		Bundle extras = getIntent().getExtras();
		int poi_id = extras != null && extras.containsKey(ARG_POI_ID) ? Integer
				.parseInt(extras.getString(ARG_POI_ID)) - 1 : 0;
		this.onItemSingleTapUp(poi_id, itemizedoverlay.getItem(poi_id));

		mapOverlays.add(itemizedoverlay);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_tour, menu);

		menu.findItem(R.id.clear_map).setOnMenuItemClickListener(
				new OnMenuItemClickListener() {
					@Override
					public boolean onMenuItemClick(MenuItem item) {
						for (Overlay o : mapView.getOverlays()) {
							if (o instanceof PathOverlay) {
								// Removed the path overlay
								mapView.getOverlays().remove(o);
							}
							// else if (o instanceof ItemizedIconOverlay) {
							// if (((ItemizedIconOverlay) o).size() == 1) {
							// // Removed my location overlay
							// mapView.getOverlays().remove(o);
							// ((ImageButton) findViewById(R.id.takeMeThere))
							// .setEnabled(false);
							// ((ImageButton) findViewById(R.id.takeMeThere))
							// .setClickable(false);
							// }
							// }
						}
						mapView.postInvalidate();
						return true;
					}
				});
		return true;
	}

	@Override
	protected void onStart() {
		super.onStart();

		// This verification should be done during onStart() because the system
		// calls this method when the user returns to the activity, which
		// ensures the desired location provider is enabled each time the
		// activity resumes from the stopped state.
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		final boolean gpsEnabled = locationManager
				.isProviderEnabled(LocationManager.GPS_PROVIDER);

		if (!gpsEnabled) {
			// Build an alert dialog here that requests that the user enable
			// the location services, then when the user clicks the "OK" button,
			// call enableLocationSettings()

			AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
					this);

			// set title
			alertDialogBuilder.setTitle(getResources().getString(
					R.string.enable_gps_title));

			// set dialog message
			alertDialogBuilder
					.setMessage(
							getResources().getString(R.string.enable_gps_text))
					.setPositiveButton(
							getResources().getString(R.string.enable_gps_yes),
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// if this button is clicked call
									// enableLocationSettings()
									enableLocationSettings();
								}
							})
					.setNegativeButton(
							getResources().getString(R.string.enable_gps_no),
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// if this button is clicked, just close the
									// dialog box and do nothing
									dialog.cancel();
								}
							});

			// create alert dialog
			AlertDialog alertDialog = alertDialogBuilder.create();

			// show it
			alertDialog.show();
		}
	}

	private void enableLocationSettings() {
		Intent settingsIntent = new Intent(
				Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		startActivity(settingsIntent);
	}

	/**
	 * Called when the user clicks the point of interest detail button
	 * 
	 * @param view
	 */
	public void poiDetail(View view) {
		int index = Integer.parseInt(poiId.getText().toString());

		Intent detailIntent = new Intent(getApplicationContext(),
				PointOfInterestDetailActivity.class);
		detailIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
				| Intent.FLAG_ACTIVITY_NEW_TASK);
		detailIntent.putExtra(PointOfInterestDetailFragment.ARG_ITEM_ID,
				String.valueOf(index));

		startActivity(detailIntent);
		finish();
	}

	/**
	 * Called when the user clicks the previous point of interest button
	 * 
	 * @param view
	 */
	public void previousPoi(View view) {
		int index = Integer.parseInt(poiId.getText().toString());
		if (index > 1) {
			onItemSingleTapUp(index - 2, itemizedoverlay.getItem(index - 2));
		}
	}

	/**
	 * Called when the user clicks the next point of interest button
	 * 
	 * @param view
	 */
	public void nextPoi(View view) {
		int index = Integer.parseInt(poiId.getText().toString());
		if (index < itemizedoverlay.size()) {
			onItemSingleTapUp(index, itemizedoverlay.getItem(index));
		}
	}

	/**
	 * Called when the user clicks the Take me there button
	 * 
	 * @param view
	 */
	public void takeMeThere(View view) {
		GeoPoint destination = itemizedoverlay.getItem(
				Integer.parseInt(poiId.getText().toString()) - 1).getPoint();
		Log.d(this.getClass().getSimpleName(),
				"Computing directions to point [" + poiId.getText().toString()
						+ "]");
		showDirectionsTo(myLocation, destination);
	}

	@Override
	public void onPause() {
		super.onPause();
		dbHelper.close();
		locationManager.removeUpdates(this);
	}

	@Override
	public void onResume() {
		super.onResume();
		dbHelper.openDataBase();
		LocationProvider provider = locationManager
				.getProvider(LocationManager.GPS_PROVIDER);
		if (provider != null) {
			providerName = provider.getName();
			locationManager.requestLocationUpdates(providerName, 400, 1, this);
		} else {
			AlertDialog alertDialog = new AlertDialog.Builder(Tour.this)
					.create();

			// Setting Dialog Title
			alertDialog.setTitle("Alert Dialog");

			// Setting Dialog Message
			alertDialog.setMessage("No suitable provider was found");

			// Setting Icon to Dialog
			alertDialog.setIcon(android.R.drawable.ic_dialog_info);

			// Setting OK Button
			alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					dialog.cancel();
				}
			});

			// Showing Alert Message
			alertDialog.show();
		}
	}

	@Override
	public boolean onItemLongPress(int index, OverlayItem item) {
		return false;
	}

	@Override
	public boolean onItemSingleTapUp(int index, OverlayItem item) {
		if (poiId.getText() != "") {
			int oldIndex = Integer.parseInt(poiId.getText().toString());
			Log.d(this.getClass().getSimpleName(), "Single tap on item ["
					+ oldIndex + "]");
			itemizedoverlay.getItem(oldIndex - 1).setMarker(
					this.getResources().getDrawable(R.drawable.red_circle));
		}
		item.setMarker(this.getResources().getDrawable(R.drawable.green_circle));
		poiName.setText(item.getTitle());
		poiId.setText(String.valueOf(index + 1));
		mapView.getController().animateTo(item.getPoint());
		int currIndex = Integer.parseInt(poiId.getText().toString());
		((ImageButton) findViewById(R.id.previousPoi))
				.setClickable(currIndex > 1);
		((ImageButton) findViewById(R.id.previousPoi))
				.setEnabled(currIndex > 1);
		((ImageButton) findViewById(R.id.nextPoi))
				.setClickable(currIndex < itemizedoverlay.size());
		((ImageButton) findViewById(R.id.nextPoi))
				.setEnabled(currIndex < itemizedoverlay.size());
		return true;
	}

	@Override
	public void onLocationChanged(Location location) {
		myLocation = location;

		if (mapView.getOverlays().size() > 1) {
			mapView.getOverlays().remove(mapView.getOverlays().size() - 1);
		}

		OverlayItem item = new OverlayItem("My location", "My location",
				new GeoPoint(location.getLatitude(), location.getLongitude()));
		item.setMarker(getResources().getDrawable(R.drawable.man));

		ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
		items.add(item);

		myLocationOverlay = new ItemizedIconOverlay<OverlayItem>(
				getApplicationContext(), items,
				new OnItemGestureListener<OverlayItem>() {
					@Override
					public boolean onItemLongPress(int arg0, OverlayItem arg1) {
						return true;
					}

					@Override
					public boolean onItemSingleTapUp(int arg0, OverlayItem arg1) {
						return true;
					}
				});
		mapView.getOverlays().add(myLocationOverlay);
		mapView.postInvalidate();
		((ImageButton) findViewById(R.id.takeMeThere)).setEnabled(true);
		((ImageButton) findViewById(R.id.takeMeThere)).setClickable(true);
	}

	@Override
	public void onProviderDisabled(String provider) {
		Toast.makeText(this, "Disabled provider: " + provider,
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onProviderEnabled(String provider) {
		Toast.makeText(this, "Enabled new provider: " + provider,
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// Do nothing
	}

	protected void showDirectionsTo(final Location start, final GeoPoint end) {
		Overlay routeOverlay = mapView.getOverlays().get(0);
		if (routeOverlay instanceof PathOverlay) {
			mapView.getOverlays().remove(0);
		}
		blueLine = new BlueLine(Color.BLUE, this);
		// the routing will be requested from another thread, need to make
		// coordinates accessible from there
		blueLine.setEndLat((double) end.getLatitudeE6() / (double) 1000000);
		blueLine.setEndLng((double) end.getLongitudeE6() / (double) 1000000);
		new Handler().post(new Runnable() {
			public void run() {
				try {
					// will always request directions from current location,
					// destination was assigned previously
					blueLine.showDirectionsToPredefinedLocation(
							start.getLatitude(), start.getLongitude(), false,
							"en", true);
					for (String instruction : blueLine.getInstructions()) {
						Log.d(this.getClass().getSimpleName(), instruction);
					}
					mapView.getOverlays().add(0, blueLine);
					mapView.postInvalidate();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

}